import json
import os
import tempfile
import re

import numpy as np
from flask import Flask, request, jsonify
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
from flask_cors import CORS

from predicted_server import find_mushroom_by_type, load_mushroom_data

# 加载类别标签
def load_class_labels(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        return json.load(f)

def load_latest_model_info():
    """加载最新的模型信息"""
    try:
        with open('model/models_info.json', 'r', encoding='utf-8') as f:
            models_list = json.load(f)
        
        if not models_list:
            raise ValueError("没有找到可用的模型信息")
        
        # 按时间戳排序，获取最新的模型
        latest_model = sorted(models_list, key=lambda x: x['timestamp'])[-1]
        print(f"加载模型: {latest_model['model_path']}")
        print(f"模型准确率: {latest_model.get('test_accuracy', 'N/A')}")
        return latest_model
    except Exception as e:
        print(f"加载模型信息时出错: {e}")
        return None

# 修改模型加载部分
model_info = load_latest_model_info()
if model_info:
    model = load_model(model_info['model_path'])
else:
    raise ValueError("无法加载模型信息")

class_labels = load_class_labels('model/class_labels.json')  # 确保该文件存在
mushroom_data = load_mushroom_data()

def predict_image(img_array, top_n=3):
    # 进行预测
    predictions = model.predict(img_array)
    
    # 获取前 top_n 个预测结果及其置信度
    top_indices = np.argsort(predictions[0])[-top_n:][::-1]
    top_classes = [(class_labels[i], predictions[0][i]) for i in top_indices]
    
    return top_classes

def predict_top1(img_path):
    # 加载图像并进行预处理
    img = image.load_img(img_path, target_size=(150, 150))  # 根据您的模型输入大小调整
    img_array = image.img_to_array(img)
    img_array = np.expand_dims(img_array, axis=0)
    img_array = preprocess_input(img_array)  # 归一化处理
    
    # 进行预测
    predictions = model.predict(img_array)
    
    # 获取最高置信度的预测结果
    top_index = np.argmax(predictions[0])
    top_class = class_labels[top_index]
    confidence = predictions[0][top_index]
    
    return top_class, confidence

app = Flask(__name__)
CORS(app)  # 允许所有域的跨域请求

@app.route('/predict', methods=['POST'])
def predict():
    try:
        if 'image' not in request.files:
            return jsonify({'status': 'error', 'message': 'No image file provided'}), 400

        file = request.files['image']
        if file.filename == '':
            return jsonify({'status': 'error', 'message': 'No selected file'}), 400

        # 保存上传的图像文件到服务器的临时目录
        temp_dir = tempfile.gettempdir()
        file_path = os.path.join(temp_dir, file.filename)
        file.save(file_path)
        print('File saved to {}'.format(file_path))

        # 进行图像处理和预测
        predicted_type, confidence = predict_top1(file_path)

        mushroom_info = find_mushroom_by_type(predicted_type, mushroom_data)
        if mushroom_info:
            return jsonify({
                'status': 'success',
                'predicted_type': predicted_type,
                'confidence': str(confidence),
                'mushroom_details': mushroom_info
            })
        else:
            return jsonify({
                'status': 'error',
                'message': f'No detailed information found for mushroom type: {predicted_type}'
            }), 404

    except Exception as e:
        return jsonify({'status': 'error', 'message': f'Error processing request: {str(e)}'}), 500

@app.route('/search', methods=['GET'])
def search():
    print(mushroom_data)
    keyword = request.args.get('keyword', '')
    # 如果 keyword 为空，返回所有数据
    if not keyword:
        return jsonify({
            'status': 'success',
            'data': mushroom_data,
        })
    # 模糊匹配关键词
    results = [mushroom for mushroom in mushroom_data if
              re.search(re.escape(keyword), mushroom['type_chinese_name'], re.IGNORECASE)]

    return jsonify({
        'status': 'success',
        'data': results,
    })

def load_mushroom_data():
    """加载并验证 mushroom.json 数据"""
    try:
        with open('mushroom.json', 'r', encoding='utf-8') as f:
            content = f.read()
            # 打印出错误位置附近的内容以便调试
            error_pos = 2529
            print("Error position content:", content[error_pos-50:error_pos+50])
            return json.loads(content)
    except json.JSONDecodeError as e:
        print(f"JSON 解析错误: {str(e)}")
        print(f"错误位置附近的内容: {content[e.pos-50:e.pos+50]}")
        # 返回空列表作为后备方案
        return []
    except Exception as e:
        print(f"加载蘑菇数据时出错: {e}")
        return []

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=4900)
